﻿using Sidvall.Serialization;
using Sidvall.UI.Dialogs;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace Sidvall.UI.Wpf.Controls
{
    public partial class WebSecurityControl : UserControl
    {
        #region Public Members

        public event System.EventHandler CloseSelected;

        #region LogManager

        private Sidvall.Logging.LogManager _LogManager;
        public Sidvall.Logging.LogManager LogManager
        {
            get
            {
                if (_LogManager != null)
                    return _LogManager;
                return Sidvall.SystemContext.Current.LogManager;
            }
            set
            {
                _LogManager = value;
            }
        }

        #endregion

        #region InitializeContext

        public void InitializeContext(LogOffDialogContext context)
        {
            if (context == null)
                throw new System.ArgumentNullException("context");

            this.LogOnContext = null;
            this.LogOffContext = context;
            var client = Sidvall.SystemContext.Current.AuthenticationManager.GetAuthenticationClient(context.LogOffEndpoint);
            var startUrl = client.CreateLogOffAddress(context.IdentityToken, context.RedirectAddress);
            this.WebView.Navigate(new System.Uri(startUrl), null, null, "Cache-Control: no-cache\r\n");
        }
        public void InitializeContext(LogOnDialogContext context)
        {
            if (context == null)
                throw new System.ArgumentNullException("context");

            this.LogOnContext = context;
            this.LogOffContext = null;
            var client = Sidvall.SystemContext.Current.AuthenticationManager.GetAuthenticationClient(context.AuthorizeEndpoint);
            var startUrl = client.CreateAuthorizeAddress(context.ClientId, context.ResponseType, context.Scope, context.RedirectAddress, context.State, context.Nonce,
                context.LogOnHint, context.AuthenticationContextReferences, context.Prompt, context.ResponseMode, context.CodeChallenge, context.CodeChallengeMethod, context.AdditionalValues);
            this.WebView.Navigate(new System.Uri(startUrl), null, null, "Cache-Control: no-cache\r\n");
        }

        #endregion
        #region LogAsync

        public async Task LogAsync(System.Exception ex)
        {
            if (this.LogManager != null)
                await this.LogManager.WriteAsync(ex, Sidvall.Logging.LogCategories.Application);
        }
        public async Task LogAsync(string title, string message, Logging.EventType severity)
        {
            if (this.LogManager != null)
                await this.LogManager.WriteAsync(title, message, Sidvall.Logging.LogCategories.Application, severity);
        }

        #endregion

        #endregion
        #region Private Members

        private LogOffDialogContext LogOffContext { get; set; }
        private LogOnDialogContext LogOnContext { get; set; }

        #region OnCloseSelected

        private void OnCloseSelected()
        {
            OnCloseSelected(new System.EventArgs());
        }
        private void OnCloseSelected(System.EventArgs args)
        {
            OnCloseSelected(this, args);
        }
        private void OnCloseSelected(object sender, System.EventArgs args)
        {
            if (this.CloseSelected != null)
                this.CloseSelected.Invoke(sender, args);
        }

        #endregion

        #endregion
        #region Events

        #region WebView_Navigating

        private async void WebView_Navigating(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e)
        {
            System.Uri callbackUri;

            if (this.LogOffContext != null)
            {
                callbackUri = new System.Uri(this.LogOffContext.RedirectAddress);
                if (e.Uri.ToString().StartsWith(callbackUri.AbsoluteUri, System.StringComparison.OrdinalIgnoreCase))
                {
                    this.LogOffContext.Response = e.Uri.AbsoluteUri;
                    e.Cancel = true;
                    OnCloseSelected();
                }
            }
            if (this.LogOnContext != null)
            {
                if (e.Uri != null)
                {
                    callbackUri = new System.Uri(this.LogOnContext.RedirectAddress);
                    if (e.Uri.ToString().StartsWith(callbackUri.AbsoluteUri, System.StringComparison.OrdinalIgnoreCase))
                    {
                        this.LogOnContext.AuthorizeResponse = Sidvall.SystemContext.Current.AuthenticationManager.ParseAuthorizeResponseFromAddress(e.Uri.AbsoluteUri);
                        this.LogOnContext.StoreResponses = true;
                        e.Cancel = true;
                        OnCloseSelected();
                    }
                    else
                    {
                        await LogAsync("WebView_Navigating", e.Uri.ToString(), Logging.EventType.Information);
                    }
                }
            }
        }

        #endregion
        #region WebView_LoadCompleted

        private void WebView_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            mshtml.HTMLDocument document;

            if (this.LogOffContext != null)
            {
                document = this.WebView.Document as mshtml.HTMLDocument;
                if (document.body.innerHTML.Contains("you are now logged out", System.StringComparison.OrdinalIgnoreCase))
                {
                    OnCloseSelected();
                }
            }
        }

        #endregion

        #endregion
        #region Constructors

        public WebSecurityControl()
        {
            InitializeComponent();

            this.WebView.Navigating += WebView_Navigating;
            this.WebView.LoadCompleted += WebView_LoadCompleted;
        }

        #endregion
    }
}
